using System;
using System.Collections.Generic;

using SBPweb.Common.Authorization;
using SBPweb.Common.Caching;
using SBPweb.Common.Session;

using SBPweb.PROvibe.Resources.Warehouse.Stream;

using SBPweb.PROvibe.Business.Logic;

namespace SBPweb.PROvibe.Business.Warehouse
{
	public class StreamFactory
	{

		#region Private static string constants

		private static string CACHEKEY_STREAMS = "Warehouse.Streams";
		private static string CACHEKEY_STREAMS_INDEX_ID = "Warehouse.Streams.Index.Id";

		private static string SESSIONKEY_STREAMS = "_Repository.Streams";

		#endregion

		#region Private fields


		#endregion

		#region Constructor logic

		private StreamFactory()
		{
		}

		#endregion

        #region Internal static properties

        internal static StreamRepository DefaultRepository
        {
            get
            {
                StreamRepository ret = SessionHandler.Get<StreamRepository>(SESSIONKEY_STREAMS);

                if (ret == null)
                {
                    ret = new StreamRepository(ConfigurationManager.ConnectionStrings.Warehouse);
                    SessionHandler.Put<StreamRepository>(SESSIONKEY_STREAMS, ret);
                }

                return ret;
            }
        }

        #endregion

        #region Repository handler methods

        #region Create

        public static Entities.Stream CreateStream(byte[] rawData)
		{
			Resources.Entities.Stream stream = new Resources.Entities.Stream();

			stream.RawData = rawData;

			DefaultRepository.Add(stream);

			return ConvertResourcesEntity(stream);
		}

		#endregion

		#region Read

		public static List<Entities.Stream> ReadStreams()
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_STREAMS))
			{
				return CacheHandler.Retrieve<List<Entities.Stream>>(CACHEKEY_STREAMS);
			}

			List<Entities.Stream> streams = ConvertResourcesEntityList(DefaultRepository.GetStreams());

			if (isCached)
			{
				CacheHandler.Store<List<Entities.Stream>>(CACHEKEY_STREAMS, streams, ConfigurationManager.CacheExpirations.Warehouse.Streams);

				Dictionary<int, Entities.Stream> indexId = new Dictionary<int, Entities.Stream>();
				Dictionary<string, Entities.Stream> indexName = new Dictionary<string, Entities.Stream>();

				foreach (Entities.Stream stream in streams)
				{
					indexId.Add(stream.Id, stream);
				}

				CacheHandler.Store<Dictionary<int, Entities.Stream>>(CACHEKEY_STREAMS_INDEX_ID, indexId, ConfigurationManager.CacheExpirations.Warehouse.Streams);
			}

			return streams;
		}

		public static Entities.Stream ReadStreamById(int streamId)
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;
			Dictionary<int, Entities.Stream> index = null;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_STREAMS_INDEX_ID))
			{
				index = CacheHandler.Retrieve<Dictionary<int, Entities.Stream>>(CACHEKEY_STREAMS_INDEX_ID);
				if (index.ContainsKey(streamId))
				{
					return index[streamId];
				}
			}

			Resources.Entities.Stream resource = DefaultRepository.GetStreamById(streamId);
            Entities.Stream stream = null;
            if (resource != null)
            {
                stream = ConvertResourcesEntity(resource);
            }

			if (index != null)
			{
				index.Add(streamId, stream);
			}

			return stream;
		}

		#endregion

		#region Update

		public static void UpdateStream(Entities.Stream stream)
		{
			DefaultRepository.Update(stream);
		}

		#endregion

		#region Delete

		public static void DeleteStream(int streamId)
		{
			DefaultRepository.Remove(streamId);
		}

		public static void DeleteStream(Entities.Stream stream)
		{
			DeleteStream(stream.Id);
		}

		#endregion

		#endregion

		#region Internal converter methods

		internal static List<Entities.Stream> ConvertResourcesEntityList(List<Resources.Entities.Stream> list)
		{
			return list.ConvertAll<Entities.Stream>(new Converter<Resources.Entities.Stream, Entities.Stream>(ConvertResourcesEntity));
		}

		internal static Entities.Stream ConvertResourcesEntity(Resources.Entities.Stream stream)
		{
			return new Entities.Stream(stream);
		}

		#endregion

	}

}